import type { BasicTableProps, BasicColumn } from '../types/table';
import type { TableRowSelection } from '../types/tableRowSelection';
import { Ref, ComputedRef, ref } from 'vue';
import { computed, unref, nextTick, watch } from 'vue';
import { getViewportOffset } from '@/utils/domUtils';
import { isBoolean } from '@/utils/is';
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn';
import { useModalContext } from '#/Modal';
import { onMountedOrActivated } from '@/hooks/core/onMountedOrActivated';
import { useDebounceFn } from '@vueuse/core';

export function useTableScroll(
	propsRef: ComputedRef<BasicTableProps>,
	tableElRef: Ref<ComponentRef>,
	columnsRef: ComputedRef<BasicColumn[]>,
	rowSelectionRef: ComputedRef<TableRowSelection | null>,
	getDataSourceRef: ComputedRef<Recordable[]>,
	wrapRef: Ref<HTMLElement | null>,
	formRef: Ref<ComponentRef>,
	isFixedHeightPage: boolean,
) {
	const tableHeightRef: Ref<Nullable<number | string>> = ref(167);
	const modalFn = useModalContext();

	// Greater than animation time 280
	const debounceRedoHeight = useDebounceFn(redoHeight, 100);

	const getCanResize = computed(() => {
		const { canResize, scroll } = unref(propsRef);
		return canResize && !(scroll || {}).y;
	});

	watch(
		() => [unref(getCanResize), unref(getDataSourceRef)?.length],
		() => {
			debounceRedoHeight();
		},
		{
			flush: 'post',
		},
	);

	function redoHeight() {
		nextTick(() => {
			calcTableHeight();
		});
	}

	function setHeight(height: number) {
		tableHeightRef.value = height;
		//  Solve the problem of modal adaptive height calculation when the form is placed in the modal
		modalFn?.redoModalHeight?.();
	}

	// No need to repeat queries
	let paginationEl: HTMLElement | null;
	let footerEl: HTMLElement | null;
	let bodyEl: HTMLElement | null;

	async function calcTableHeight() {
		const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } = unref(propsRef);
		const tableData = unref(getDataSourceRef);

		const table = unref(tableElRef);
		if (!table) return;

		const tableEl: Element = table.$el;
		if (!tableEl) return;

		if (!bodyEl) {
			bodyEl = tableEl.querySelector('.ant-table-body');
			if (!bodyEl) return;
		}

		const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight;
		const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth;

		if (hasScrollBarY) {
			tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.remove('hide-scrollbar-y');
		} else {
			!tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y');
		}

		if (hasScrollBarX) {
			tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.remove('hide-scrollbar-x');
		} else {
			!tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x');
		}

		bodyEl!.style.height = 'unset';

		if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) return;

		await nextTick();
		// Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight

		const headEl = tableEl.querySelector('.ant-table-thead ');

		if (!headEl) return;

		// Table height from bottom height-custom offset
		let paddingHeight = 32;
		// Pager height
		let paginationHeight = 2;
		if (!isBoolean(pagination)) {
			paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement;
			if (paginationEl) {
				// 简单处理：根据PageWrapper的padding值手动设置offset
				let offset = 0;
				if (isFixedHeightPage) {
					offset = 8;
				}
				const offsetHeight = paginationEl.offsetHeight + offset;
				paginationHeight += offsetHeight || 0;
			} else {
				// TODO First fix 24
				paginationHeight += 32;
			}
		} else {
			paginationHeight = -8;
		}

		let footerHeight = 0;
		if (!isBoolean(pagination)) {
			if (!footerEl) {
				footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
			} else {
				const offsetHeight = footerEl.offsetHeight;
				footerHeight += offsetHeight || 0;
			}
		}

		let headerHeight = 0;
		if (headEl) {
			headerHeight = (headEl as HTMLElement).offsetHeight;
		}

		let bottomIncludeBody = 0;
		if (unref(wrapRef) && isCanResizeParent) {
			const tablePadding = 12;
			const formMargin = 16;
			let paginationMargin = 10;
			const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0;

			let formHeight = unref(formRef)?.$el.offsetHeight ?? 0;
			if (formHeight) {
				formHeight += formMargin;
			}
			if (isBoolean(pagination) && !pagination) {
				paginationMargin = 0;
			}
			if (isBoolean(useSearchForm) && !useSearchForm) {
				paddingHeight = 0;
			}

			const headerCellHeight = (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0;

			console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin);
			bottomIncludeBody = wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin;
		} else {
			// Table height from bottom
			bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody;
		}

		let height =
			bottomIncludeBody -
			(resizeHeightOffset || 0) -
			paddingHeight -
			paginationHeight -
			footerHeight -
			headerHeight;
		height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
		setHeight(height);

		bodyEl!.style.height = `${height}px`;
	}

	useWindowSizeFn(calcTableHeight, 280);
	onMountedOrActivated(() => {
		calcTableHeight();
		nextTick(() => {
			debounceRedoHeight();
		});
	});

	const getScrollX = computed(() => {
		let width = 0;
		if (unref(rowSelectionRef)) {
			width += 60;
		}

		// TODO props ?? 0;
		const NORMAL_WIDTH = 150;

		const columns = unref(columnsRef).filter(item => !item.defaultHidden);
		columns.forEach(item => {
			width += Number.parseInt(item.width as string) || 0;
		});
		const unsetWidthColumns = columns.filter(item => !Reflect.has(item, 'width'));

		const len = unsetWidthColumns.length;
		if (len !== 0) {
			width += len * NORMAL_WIDTH;
		}

		const table = unref(tableElRef);
		const tableWidth = table?.$el?.offsetWidth ?? 0;
		return tableWidth > width ? '100%' : width;
	});

	const getScrollRef = computed(() => {
		const tableHeight = unref(tableHeightRef);
		const { canResize, scroll } = unref(propsRef);
		return {
			x: unref(getScrollX),
			y: canResize ? tableHeight : null,
			scrollToFirstRowOnChange: false,
			...scroll,
		};
	});

	return { getScrollRef, redoHeight };
}
